package com.yc.api2;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Company 源辰信息
 *
 * @author navy
 * @date 2024/11/5
 * Email haijunzhou@hnit.edu.cn
 */
public class MyHashMap<K,V> implements Map<K,V> {

    public static void main(String[] args) {
        MyHashMap<String, Student> map = new MyHashMap<>();
        map.put("001", new Student("张三",12));
        map.put("002", new Student("李四",13));
        map.put("002", new Student("李四",13));
        map.put("003", new Student("王五",14));
        map.put("004", new Student("李四",19));
        System.out.println("map.size() = " + map.size());

        Student s1 = map.get("001");
        Student s2 = map.get("002");
        Student s3 = map.get("009");

        System.out.println("s1 = " + s1);
        System.out.println("s2 = " + s2);
        System.out.println("s3 = " + s3);

        System.out.println("------------------------");
        Student stu = map.remove("001");
        System.out.println("删除的元素: stu001 = " + stu);
        System.out.println("剩下的元素: map.size() = " + map.size());

        stu = map.remove("009");
        System.out.println("删除的元素: stu009 = " + stu);
        System.out.println("剩下的元素: map.size() = " + map.size());

        System.out.println("------------------------");
        System.out.println("map.containsKey(\"001\") = " + map.containsKey("001")); // false
        System.out.println("map.containsKey(\"002\") = " + map.containsKey("002")); // true

        System.out.println("------------------------");
        for (String key : map.keySet()) {
            System.out.println("key = " + key);
        }
    }

    MyEntry<K,V>[] table = new MyEntry[11];
    int count = 0;

    // 空方法 => 方法存根
    @Override
    public int size() {
        return count;
    }

    @Override
    public V put(K key, V value) {
        // key => 键 学号, 手机号, 邮箱地址....
        // 创建 entry
        MyEntry<K,V> myEntry = new MyEntry<>();
        myEntry.key = key;
        myEntry.value = value;

        // 计算 hash => 地址
        int hash = key.hashCode();
        int index = hash % table.length;

        // table 查找对应的元素  equals 相同=>替换  or 不同 hash冲突 => 写入链表中
        if (table[index] == null) {
            // 当前hash值地址没有元素
            table[index] = myEntry;
            count ++;
        } else {
            // 当前hash值地址有元素
            // 当前指针(对象)
            MyEntry me = table[index];
            // 当前指针(对象)的上一个元素(对象)
            MyEntry pre = null;
            while(me!=null){
                if (me.value.equals(value)){
                    // 内容相同替换
                    me.value = value;
                    // count 不用 + 1
                    return value;
                } else {
                    pre = me;
                    me = me.next;
                }
            }
            pre.next = myEntry;
            count ++;
        }
        return value;
    }

    @Override
    public V get(Object key) {
        int index = key.hashCode() % table.length;
        if(table[index] == null){
            return null;
        } else {
            MyEntry<K,V> me = table[index];
            while(me!=null){
                if(me.key.equals(key)){
                    // 找到了元素
                    return me.value;
                } else {
                    me = me.next;
                }
            }
        }
        return null;
    }

    @Override
    public V remove(Object key) {
        int index = key.hashCode() % table.length;
        if(table[index] == null){
            return null;
        } else {
            MyEntry<K,V> me = table[index];
            MyEntry<K,V> pre = null;
            while(me!=null){
                if(me.key.equals(key)){
                    // 找到了元素
                    V ret =  me.value;
                    // 拆链
                    if(pre != null){
                        // 有可能删除的是第一个元素, 链头, 没有上一个元素
                        pre.next = me.next;
                    } else {
                        // 当前链只有一个元素, 直接将链头设置为 null
                        table[index] = null;
                    }
                    // 计数器 减一
                    count --;
                    return ret;
                } else {
                    pre = me;
                    me = me.next;
                }
            }
        }
        return null;
    }

    @Override
    public boolean containsKey(Object key) {
        int index = key.hashCode() % table.length;
        if(table[index] == null){
            return false;
        } else {
            MyEntry<K,V> me = table[index];
            while(me!=null){
                if(me.key.equals(key)){
                    return true;
                } else {
                    me = me.next;
                }
            }
        }
        return false;
    }

    @Override
    public Set<K> keySet() {
        Set<K> ret = new HashSet<>();
        for (MyEntry<K, V> e : table) {
            if(e!=null){
                MyEntry<K,V> me = e;
                while(me!=null){
                    ret.add(me.key);
                    me = me.next;
                }
            }
        }
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean containsValue(Object value) {
        return false;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {

    }

    @Override
    public void clear() {

    }

    @Override
    public Collection<V> values() {
        // Collection<V> List 和 Set 共同父类, 能不用 Set 集合? 不可以, map集合运行 value 重复
        // Collection<V> ret = new XxxxList<>();
        return null;
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        return null;
    }

    /////////////////////////////////////////////////////////////////

    class MyEntry<K,V> implements Entry<K,V>{

        K key;
        V value;
        MyEntry<K,V> next;

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            return this.value = value;
        }
    }
}
